module Form.MenuItem;
private import Graphics.IGraphics;
private import System.Console;
private import std.string;

public class TextAlign {
	public static const int LEFT   =  0;
	public static const int CENTER =  1;
	public static const int RIGHT  =  2;
	public static const int TOP    =  4;
	public static const int MIDDLE =  8;
	public static const int BOTTOM = 16;
} //

	
public interface IMenuItem : IDrawingEntry{
	
	IMenuItem up();
	IMenuItem down();
	IMenuItem left();
	IMenuItem right();
	void select();
	void onGetFocus();
	void onLostFocus();
	void connectDown(IMenuItem im);
	void connectUp(IMenuItem im);
	void connectLeft(IMenuItem im);
	void connectRight(IMenuItem im);
	string text();
	void text( string v );
	bool active();
	IMenuItem activate();
	bool action();
	

//	void SetImage(Image img);
//	void SetTexture(Texture tex);
		
	void setSelectHandler(    void delegate( IMenuItem im )  handle );
	void setGetFocusHandler(  void delegate( IMenuItem im )  handle );
	void setLostFocusHandler( void delegate( IMenuItem im )  handle );
} //

public class MenuItemConnector{
	public static void connectVertical( IMenuItem[] items ) {
		for ( int i = 0 ; i < items.length - 1 ; i++ ) {
			items[ i + 1 ].connectUp( items[ i ] );
			items[ i ].connectDown( items[ i + 1] );
		}
		items[ 0 ].connectUp( items[ items.length - 1 ] );
		items[ items.length - 1 ].connectDown(items[ 0 ]);
	}
	public static void connectHorizontal( IMenuItem[] items ) {
		for ( int i = 0 ; i < items.length - 1 ; i++ ) {
			items[ i + 1 ].connectLeft( items[ i ] );
			items[ i ].connectRight( items[ i + 1 ] );
		}
		items[ 0 ].connectLeft( items[ items.length - 1 ] );
		items[ items.length - 1 ].connectRight( items[ 0 ] );
	}
} //

public class MenuItem : IDrawingEntry , IMenuItem {
	protected void delegate( IMenuItem im ) _onSelectHandler , _onGetFocusHandler , _onLostFocusHandler;

	protected bool _visible = true , _alive = true;
	protected int _innerTimer = 0;
	protected float _x = 0 , _y = 0 , _z = 0;
	protected float _width = 0 , _height= 0 , _fontHeight = 16 , _fontWidth = 8;
	protected static Color defaultColor;
	protected IMenuItem _downMenu , _upMenu , _leftMenu , _rightMenu;
	protected bool _active = false;

	protected int _hAlign = TextAlign.CENTER;
	protected int _vAlign = TextAlign.MIDDLE;
	protected Color _currentColor;
	protected Color _activeColor  ;
	protected Color _activeColor2 ;
	protected Color _normalColor  ;

	public float x(){return _x;}
	public float y(){return _y;}
	public float z(){return _z;}
	
	public void x( float v ) { _x = v; }
	public void y( float v ) { _y = v; }
	public void z( float v ) { _z = v; }

	 public float width() { return _width;}
	 public float height() { return _height;}
	 public float fontWidth()  { return _fontWidth;}
	 public float fontHeight() { return _fontHeight;}
	 public int  HorizontalAlign(){ return _hAlign;}
	 public int  VerticalAlign()  { return _vAlign;}
	 public void HorizontalAlign( int num ){ _hAlign = num;}
	 public void VerticalAlign( int num )  { _vAlign = num;}

	 public void fontWidth(  float v ) { _fontWidth  = v ; text = _text;}
	 public void fontHeight( float v ) { _fontHeight = v ; text = _text;}

	 public Color activeColor (){ return _activeColor;}
	 public Color activeColor2(){ return _activeColor2;}
	 public Color normalColor (){ return _normalColor;}
	 public void  activeColor ( Color c ) { _activeColor  = c;}
	 public void  activeColor2( Color c ) { _activeColor2 = c;}
	 public void  normalColor ( Color c ) { _normalColor  = c;}

	public bool active(){ return _active; }
	private string _text = "MenuItem";
	public string text() { return _text;} 
	public void text( string tex ) {
		_text = tex;
		_width  = _fontWidth  * tex.length;
		_height = _fontHeight;
//		init();
	} //
	
	public this(){
		init();
	} //
	public this ( string t ) {
		text = t;
		init();
	} //

	protected void init() {
		_x = 0;
		_y = 0;
		_z = 250;
		_activeColor  = Color.create( 0xffc00000u );
		_activeColor2 = Color.create( 0xffffff00u );
		_normalColor  = Color.create( 0xffffffffu );
		_currentColor = _normalColor;
	} //

	public IMenuItem down(){
		if ( !( _downMenu is null ) ) {
			onLostFocus();
			_downMenu.onGetFocus();
			return _downMenu;
		}
		else	return this;
	} //
	public IMenuItem up(){
		if ( !( _upMenu is null ) ) {
			onLostFocus();
			_upMenu.onGetFocus();
			return _upMenu;
		}
		else	return this;
	} //
	public IMenuItem right(){
		if ( !( _rightMenu is null ) ) {
			onLostFocus();
			_rightMenu.onGetFocus();
			return _rightMenu;
		}
		else	return this;
	} //
	public IMenuItem left(){
		if ( !( _leftMenu is null ) ) {
			onLostFocus();
			_leftMenu.onGetFocus();
			return _leftMenu;
		}
		else	return this;
	} //

	public void connectDown( IMenuItem im ) {
		if ( !( _downMenu is im ) ) {
			_downMenu = im;
		}
	} //
	public void connectUp( IMenuItem im ) {
		if ( !( _upMenu is im ) ) {
			_upMenu = im;
		}
	} //
	public void connectLeft( IMenuItem im ) {
		if ( !( _leftMenu is im ) ) {
			_leftMenu = im;
		}
	} //
	public void connectRight( IMenuItem im ) {
		if ( !( _rightMenu is im ) ) {
			_rightMenu = im;
		}
	} //

	public IMenuItem activate() {
		_active = true;
		return this;
	} //

	public void select(){
		if ( !( _onSelectHandler is null ) ) _onSelectHandler( this );
	} //
	public void onGetFocus(){
		_currentColor = activeColor;
		_active = true;
		if ( !( _onGetFocusHandler is null ) ) _onGetFocusHandler(this);
	} //
	public void onLostFocus(){
		_currentColor = _normalColor;
		_active = false;
		if ( !( _onLostFocusHandler is null ) ) _onLostFocusHandler(this);
	} //
	public void setSelectHandler(    void delegate( IMenuItem im )  handle ) {
		_onSelectHandler    = handle;
	} //
	public void setGetFocusHandler(  void delegate( IMenuItem im )  handle ) {
		_onGetFocusHandler  = handle;
	} //
	public void setLostFocusHandler( void delegate( IMenuItem im )  handle ) {
		_onLostFocusHandler = handle;
	} //


	//----------------------
	public void moveTo( float xx , float yy ) {
		_x = xx;
		_y = yy;
	} //
	public bool action(){
		if ( _alive < 0 )return false;
		_innerTimer++;

		if ( _active ) {
			int sp = 100;
			int it = _innerTimer % sp * 2 ;
			if ( it > sp ) it = sp*2 - it;
			int st = sp - it;
			int r = ( _activeColor.r * it + _activeColor2.r * st ) / sp;
			int g = ( _activeColor.g * it + _activeColor2.g * st ) / sp;
			int b = ( _activeColor.b * it + _activeColor2.b * st ) / sp;
			_currentColor = Color.create( r , g , b );
		} else
			_currentColor = _normalColor;
		
		return true;
	} //

	public bool drawingEntry( IGraphics g ) {
		if ( !_visible ) return false;
		if ( !_alive )   return false;
		moveTo( x , y );
		 return g.addDrawingEntry( this );
	} //
	
	public bool draw( IGraphics g ) {
		float xx = _x;
		float yy = _y;
		if ( _hAlign == TextAlign.CENTER ) {
			xx =   xx - ( _fontWidth * _text.length ) / 2 +_fontWidth;
		} else
		if ( _hAlign == TextAlign.RIGHT ) {
			xx =   xx - ( _fontWidth * _text.length ) ;
		}
		if ( _vAlign == TextAlign.MIDDLE ) {
			xx =   xx - ( _fontHeight ) / 2 ;
		} else
		if ( _vAlign == TextAlign.MIDDLE ) {
			xx =   xx -   _fontHeight ;
		}
		g.drawText( _text , cast(int)xx , cast(int)yy , _currentColor , _fontWidth , _fontHeight );
		return true;
	} //

} // end class MenuItem
	
	
public class EnumMenuItem : MenuItem {
//	protected event OnEnumMenuChangedHandler changedHandler;
	protected void delegate( EnumMenuItem im , string selectedValue , int selectedIndex ) _changedHandler;
	private string _menuName = "";
	private string[] _values;
	private int _selectedIndex;
	private string _formatStr;

	public this( string name ){
		_menuName = name;
		super();
	} //

	public IMenuItem right(){
		_selectedIndex = ( _selectedIndex + 1 ) % _values.length;
		change();
		return this;
	} //
	public IMenuItem left(){
		_selectedIndex = ( _selectedIndex + ( _values.length - 1 ) ) % _values.length;
		change();
		return this;
	} //
	private void change(){
//		_text = _menuName ~ _values[ _selectedIndex ];
		_text = format( _formatStr , _menuName , _values[ _selectedIndex ] );
		if ( !( _changedHandler is null ) )
			_changedHandler( this , _values[ _selectedIndex ] , _selectedIndex );
	} //

	public void setChangedHandler( void delegate( EnumMenuItem im , string selectedValue , int selectedIndex ) handle ){
			_changedHandler = handle;
	} //

	private void setFormatStr( string[] val ){
		int len = 0;
		foreach( int i , string v ; val ) {
			if ( len < v.length ) len = v.length;
		}
		_formatStr = "%s %" ~ std.string.toString(len) ~ "s";
	} //

	public void setValues( string menuName , string[] val , string selected) {
		foreach( int i , string v ; val ) {
			if ( v == selected ) {
				setValues( menuName , val , i );
				return;
			}
		}
		setValues( menuName , val , 0 );
	} //
	public void setValues( string name , string[] val , int selected ) {
		setFormatStr( val );
		_menuName = name;
		_values = val;
		_selectedIndex = selected;
		_text = format( _formatStr , _menuName , _values[ _selectedIndex ] );
	} //
	
	public string value() {
		if ( _values.length > _selectedIndex ) 
			return _values[ _selectedIndex ];
		else
			return "";
	} //
} //

